package com.binguo.service;

import com.alibaba.fastjson.JSONObject;
import com.binguo.common.paymodel.MD5Util;
import com.binguo.common.paymodel.WXResponse;
import com.binguo.common.paymodel.WeixinConfig;
import com.binguo.common.paymodel.YilingPayResult;
import com.binguo.common.util.JsonUtil;
import com.binguo.common.util.PriceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

@Service
public class AliServerPayService {

    public static final HttpHeaders DEFAULT_FORM_HEADER = new HttpHeaders();

    public static final String TERMINAL_UNIQUE_NO = "001";

//    public static String key = "4bf5105f190dbf2b6d04ec06eebcb53c";
    public static String key = "822fee2804e767cdaa887d73305909a8";

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");

    private static Logger logger = LoggerFactory.getLogger(AliServerPayService.class);

    static{
        MediaType formtype = MediaType.APPLICATION_FORM_URLENCODED;
        DEFAULT_FORM_HEADER.setContentType(formtype);
    }
    private RestTemplate restTemplate = new RestTemplate();
////
    public static void main(String[] args) {
        AliServerPayService aliServerPayService = new AliServerPayService();
//        String a = aliServerPayService.qrCodePay("a5", "0.01", null, "000000000138097");
//        aliServerPayService.doPay("aaa", "3");
//

        /**
         * {"orderNo":"1567240103538106461","serialNumber":"5502801370349215183",
         * "shopId":87,"cashierDeskId":810,"openId":"73","customerId":null,
         * "customerName":null,"customerPhone":null,"customerGroupID":null,
         * "cardNo":null,"accountBalance":null,"authCode":"286614506168211993","payType":"MICROPAY","totalFee":100,"realFee":100,"totalQuantity":1,"items":[{"productId":5098,"price":100,"quantity":1}]}
         */
//        String s = PriceUtil.changeF2Y(Long.valueOf(100));
//
//        aliServerPayService.doQuery("Mi4753114c2d2f4571b02752cffeaeae9c", "000000000193035858845451953", "000000000193035", "2ba5c350b6afc8850e34f046aed55164");

//        aliServerPayService.miniPay("a1", "1", "000000000193035", "2ba5c350b6afc8850e34f046aed55164", "oyQ6P4mA40r_--iN86uQ-8kF7_mI");

//        YilingPayResult isSuccess = aliServerPayService.doPay("test091a02a83aaao9a24a4421", PriceUtil.changeF2Y(1l),
//                "135164260226561613", null, "000000000146342", "12f71b98d2f4f7ff2acf81addc38b521");
//                "135164260226561613", null, "000000000192683", "78de6e82339b29bac51b5ff530451b78");
//                "135313961773312634", null, "000000000145516", "c808b2e456846604101fd1d0283cf053");
//                "135137549285884186", null, "000000000185274", "a37eccd2c942c8be314452894eb5f787");
        YilingPayResult isSuccess = aliServerPayService.doPay("tesat3a1a3231aaa242", PriceUtil.changeF2Y(1l),
//                "288581279861978897", null, "000000000138097");
                "134615359053025804", null, "000000000155034", "5a294db46c557096f1f0058e7eb57426");
//                "134750957944605077", null, "000000000155034", "5a294db46c557096f1f0058e7eb57426");
//        System.out.println(isSuccess);
//        String orderNo = "3";
//        String traceNum = "003386102657";
//
////        aliServerPayService.doQuery(orderNo, traceNum);
//        aliServerPayService.refund("b1a3aaaaaabb","000000000141758","004150963917",PriceUtil.changeF2Y(1l),"d56494c0997fa050bf37a0e6de8b85e1");
//       aliServerPayService.doQuery("SZYunPengTest2","005402104967","000000000129128",key);
    }

    public YilingPayResult doPay(String orderNo, String total_fee, String auth_code,
                                 String cashier_num, String sub_mch_id, String key){

        String url = "https://papi.020leader.com/unipay/";

        if (StringUtils.isEmpty(sub_mch_id)) {
            sub_mch_id = "000000000129128";
        }

        if (StringUtils.isEmpty(cashier_num)) {
            cashier_num = "09607619423";//操作员编号
//            cashier_num = "09600504299";//操作员编号
        }

        String version = "2.0";
        String service = "unipay.acquire.createandpay";
        String dynamic_id = auth_code;
        String external_num = orderNo;
        String merchant_num = sub_mch_id;
        String terminal_unique_no = TERMINAL_UNIQUE_NO;
        String client_type = "web";

        SortedMap<String, String> map = new TreeMap<>();
        map.put("version", version);
        map.put("service", service);
        map.put("total_fee", total_fee);
        map.put("dynamic_id", dynamic_id);
        map.put("external_num", external_num);
        map.put("merchant_num", merchant_num);
        map.put("terminal_unique_no", terminal_unique_no);
        map.put("cashier_num", cashier_num);
        map.put("client_type", client_type);

        String signBefore = "";

        MultiValueMap multiValueMap = new LinkedMultiValueMap();

        for (Map.Entry<String, String> entry : map.entrySet()) {
            signBefore += entry.getKey() + "=" + entry.getValue() + "&";
            multiValueMap.add(entry.getKey(), entry.getValue());
        }

        signBefore += "key=" + key;

        String sign = MD5Util.MD5Upper32(signBefore);

        map.put("sign", sign);
        multiValueMap.add("sign", sign);

        System.out.println(map);




        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(multiValueMap,DEFAULT_FORM_HEADER);
        ResponseEntity<String> result = restTemplate.postForEntity(url, entity, String.class);

        System.out.println(result.getBody());
//{"result_msg":" order success pay inprocess","dynamic_type":"4","result_code":"PAYING","merchant_num":"000000000129128","trace_num":"003386102657","pay_direct":1}
        try {
            Map<String, Object> resultMap = JsonUtil.parse(result.getBody());
            String result_code = (String) resultMap.get("result_code");
            String trace_num = (String) resultMap.get("trace_num");

            if ("PAYING".equals(result_code)) {
                System.out.println(resultMap);


                int count = 0;
                boolean doWhile = false;


                logger.info(trace_num);

                while(!doWhile) {
                    try {
                        Thread.sleep(5 * 1000); //设置暂停的时间 5 秒
                        count ++ ;
                        logger.info(sdf.format(new Date()) + "--订单查询支付状态请求第" + count + "次");


                        String orderQueryResult = doQuery(orderNo, trace_num, merchant_num, key);

                        logger.info("order_result_code : {}" , orderQueryResult);

                        if ("SUCCESS".equals(orderQueryResult)) {
                            return YilingPayResult.success(trace_num);
                        }else {
                            if(!"PAYING".equals(orderQueryResult)){
                                return YilingPayResult.fail();
                            }
                        }

                        if (count == 6) {
                            doWhile = true;

                            //撤销订单
                            return YilingPayResult.fail();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }else {
                if ("SUCCESS".equals(result_code)) {
                    return YilingPayResult.success(trace_num);
                }

            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return YilingPayResult.fail();

    }

    public JSONObject qrCodePay(String orderNo, String total_fee, String cashier_num, String sub_mch_id, String dynamic_type, String payKey){
        String url = "https://papi.020leader.com/unipay/";

        if (StringUtils.isEmpty(sub_mch_id)) {
            sub_mch_id = "000000000129128";

        }

        if (StringUtils.isEmpty(cashier_num)) {
            cashier_num = "09607619423";//操作员编号
        }

        String version = "2.0";
        String service = "unipay.acquire.precreate";
        String external_num = orderNo;
        String merchant_num = sub_mch_id;
        String terminal_unique_no = TERMINAL_UNIQUE_NO;
        String client_type = "ANDROID";

        SortedMap<String, String> map = new TreeMap<>();
        map.put("version", version);
        map.put("service", service);
        map.put("total_fee", total_fee);
        map.put("external_num", external_num);
        map.put("dynamic_type", dynamic_type);
        map.put("merchant_num", merchant_num);
        map.put("terminal_unique_no", terminal_unique_no);
        map.put("cashier_num", cashier_num);
        map.put("client_type", client_type);

        String signBefore = "";

        MultiValueMap multiValueMap = new LinkedMultiValueMap();

        for (Map.Entry<String, String> entry : map.entrySet()) {
            signBefore += entry.getKey() + "=" + entry.getValue() + "&";
            multiValueMap.add(entry.getKey(), entry.getValue());
        }

        signBefore += "key=" + payKey;

        String sign = MD5Util.MD5Upper32(signBefore);

        map.put("sign", sign);
        multiValueMap.add("sign", sign);

        System.out.println(map);




        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(multiValueMap,DEFAULT_FORM_HEADER);
        ResponseEntity<String> result = restTemplate.postForEntity(url, entity, String.class);

        System.out.println(result.getBody());
        try {
            Map<String, Object> resultMap = JsonUtil.parse(result.getBody());
            String result_code = (String) resultMap.get("result_code");

            if ("SUCCESS".equals(result_code)) {
                System.out.println(resultMap);

                String qr_code = (String) resultMap.get("qr_code");

                String trace_num = (String) resultMap.get("trace_num");

                JSONObject qrCodeJson = new JSONObject();
                qrCodeJson.put("qrCode",qr_code);
                qrCodeJson.put("traceNum",trace_num);

                return qrCodeJson;
            }else {
                return null;
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;

    }


    public WXResponse miniPay(String orderNo, String total_fee, String sub_app_id, String payKey, String openId){
        String url = "https://papi.020leader.com/unipay/";

        if (StringUtils.isEmpty(sub_app_id)) {
            sub_app_id = "000000000129128";

        }

        String version = "2.0";
        String service = "pay.weixin.jspay";
        String external_num = orderNo;
        String merchant_num = sub_app_id;
        String terminal_unique_no = TERMINAL_UNIQUE_NO;

        SortedMap<String, String> map = new TreeMap<>();
        map.put("version", version);
        map.put("service", service);
        map.put("merchant_num", merchant_num);
        map.put("total_fee", PriceUtil.changeF2Y(Long.valueOf(total_fee)));
        map.put("is_minipg", "1");//0，公众号支付 1，小程序支付
        map.put("external_num", external_num);
        map.put("terminal_unique_no", terminal_unique_no);
        map.put("cashier_num", "09607619423");
        map.put("sub_appid", "wx099356561cb9c60f");
        map.put("sub_openid", openId);
        map.put("notify_url", WeixinConfig.notifyUrl);

        String signBefore = "";

        MultiValueMap multiValueMap = new LinkedMultiValueMap();

        for (Map.Entry<String, String> entry : map.entrySet()) {
            signBefore += entry.getKey() + "=" + entry.getValue() + "&";
            multiValueMap.add(entry.getKey(), entry.getValue());
        }

        signBefore += "key=" + payKey;

        String sign = MD5Util.MD5Upper32(signBefore);

        map.put("sign", sign);
        multiValueMap.add("sign", sign);

        System.out.println(map);




        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(multiValueMap,DEFAULT_FORM_HEADER);
        ResponseEntity<String> result = restTemplate.postForEntity(url, entity, String.class);

        System.out.println(result.getBody());
        try {
            Map<String, Object> resultMap = JsonUtil.parse(result.getBody());
            String result_code = (String) resultMap.get("result_code");

            if ("SUCCESS".equals(result_code)) {
                System.out.println(resultMap);

                String mch_id = (String) resultMap.get("mch_id");

                String out_trade_no = (String) resultMap.get("out_trade_no");
                String pay_info = (String) resultMap.get("pay_info");

                Map<String, Object> payInfoMap = JsonUtil.parse(pay_info);

                WXResponse wxResponse = new WXResponse();
                wxResponse.set_package((String)payInfoMap.get("package"));
                wxResponse.setNonceStr((String)payInfoMap.get("nonceStr"));
                wxResponse.setPaySign((String)payInfoMap.get("paySign"));
                wxResponse.setPrepayId((String)payInfoMap.get("package"));
                wxResponse.setSignType((String)payInfoMap.get("signType"));
                wxResponse.setTimeStamp((String)payInfoMap.get("timeStamp"));
                wxResponse.setCodeUrl(out_trade_no);
                return wxResponse;
            }else {
                return null;
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;

    }

    public String doQuery(String orderNo, String trace_num, String merchant_num, String key){
        String url = "https://papi.020leader.com/unipay/";

        String version = "2.0";
        String service = "unipay.acquire.query";
//        String merchant_num = "000000000129128";

        SortedMap<String, String> map = new TreeMap<>();
        map.put("version", version);
        map.put("service", service);
        map.put("merchant_num", merchant_num);
        map.put("trace_num", trace_num);
        map.put("external_num", orderNo);

        String signBefore = "";

        MultiValueMap multiValueMap = new LinkedMultiValueMap();

        for (Map.Entry<String, String> entry : map.entrySet()) {
            signBefore += entry.getKey() + "=" + entry.getValue() + "&";
            multiValueMap.add(entry.getKey(), entry.getValue());
        }

        signBefore += "key=" + key;

        String sign = MD5Util.MD5Upper32(signBefore);

        map.put("sign", sign);
        multiValueMap.add("sign", sign);

        System.out.println(map);

        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(multiValueMap,DEFAULT_FORM_HEADER);
        ResponseEntity<String> result = restTemplate.postForEntity(url, entity, String.class);

        System.out.println(result.getBody());

        try {
            Map<String, Object> resultMap = JsonUtil.parse(result.getBody());
            String result_code = (String) resultMap.get("result_code");

            return result_code;
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public Boolean refund(String orderNo, String sub_mch_id, String trace_num,
                          String refund_amount, String key){
        String url = "https://papi.020leader.com/unipay/";

        String version = "2.0";
        String service = "unipay.acquire.refund";
        if (StringUtils.isEmpty(sub_mch_id)) {
            sub_mch_id = "000000000129128";
        }
        String merchant_num = sub_mch_id;

        SortedMap<String, String> map = new TreeMap<>();
        map.put("version", version);
        map.put("service", service);
        map.put("merchant_num", merchant_num);
        map.put("trace_num",trace_num);
        map.put("external_num",orderNo);
        map.put("refund_amount",refund_amount);
        map.put("terminal_unique_no",TERMINAL_UNIQUE_NO);

        String signBefore = "";

        MultiValueMap multiValueMap = new LinkedMultiValueMap();

        for (Map.Entry<String, String> entry : map.entrySet()) {
            signBefore += entry.getKey() + "=" + entry.getValue() + "&";
            multiValueMap.add(entry.getKey(), entry.getValue());
        }

        signBefore += "key=" + key;

        String sign = MD5Util.MD5Upper32(signBefore);

        map.put("sign", sign);
        multiValueMap.add("sign", sign);

        System.out.println(map);

        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(multiValueMap,DEFAULT_FORM_HEADER);
        ResponseEntity<String> result = restTemplate.postForEntity(url, entity, String.class);

        System.out.println(result.getBody());

        try {
            Map<String, Object> resultMap = JsonUtil.parse(result.getBody());
            String result_code = (String) resultMap.get("result_code");

            if ("SUCCESS".equals(result_code)) {
                return true;
            }else {
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
}
